package com.xuecheng.media.config.threadpool;

import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Configuration
public class ThreadPoolAutoConfiguration {

    //线程池配属性类
    @Data
    @ConfigurationProperties(prefix = "thread-pool")
    public static class ThreadPoolProperties {
        private int coreSize = Runtime.getRuntime().availableProcessors();
        private int maxSize = coreSize * 2;
        private int queueCapacity = 100;
        private int keepAliveTime = 30;
        private String threadNamePrefix = "thread-";
        private boolean allowCoreThreadTimeout = true;
        private boolean waitForTasksCompleteOnShutdown = true;
    }

    //线程池配置属性Bean
    @Bean
    public ThreadPoolProperties threadPoolProperties() {
        return new ThreadPoolProperties();
    }

    //线程实例Bean
    @Bean(destroyMethod = "shutdown")
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolProperties properties) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                properties.getCoreSize(),
                properties.getMaxSize(),
                properties.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(properties.getQueueCapacity()),
                new NamingThreadFactory(properties.getThreadNamePrefix()),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );

        // 允许核心线程超时
        executor.allowCoreThreadTimeOut(properties.isAllowCoreThreadTimeout());

        return executor;
    }

    //线程工厂
    public static class NamingThreadFactory implements ThreadFactory {
        private final String prefix;
        private final AtomicInteger counter = new AtomicInteger(1);

        public NamingThreadFactory(String prefix) {
            this.prefix = prefix;
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r, prefix + counter.getAndIncrement());
            t.setDaemon(false);
            t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

    //停机处理器
    @Bean
    @Autowired
    public ThreadPoolShutdownHandler threadPoolShutdownHandler(ThreadPoolExecutor threadPoolExecutor, ThreadPoolProperties properties) {
        return new ThreadPoolShutdownHandler(threadPoolExecutor, properties);
    }

    //停处理具体实现
    public static class ThreadPoolShutdownHandler {
        private final ThreadPoolExecutor executor;
        private final ThreadPoolProperties properties;

        public ThreadPoolShutdownHandler(ThreadPoolExecutor executor, ThreadPoolProperties properties) {
            this.executor = executor;
            this.properties = properties;
        }

        @PostConstruct
        public void registerShutdownHook() {
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                executor.shutdown();
                try {
                    if (properties.isWaitForTasksCompleteOnShutdown()) {
                        if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
                            executor.shutdownNow();
                        }
                    } else {
                        executor.shutdownNow();
                    }
                } catch (InterruptedException e) {
                    executor.shutdownNow();
                    Thread.currentThread().interrupt();
                }
            }));
        }
    }
}